using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using DemoMvcApplication.Helpers;
using System.Web.Security;

namespace DemoMvcApplication.Controllers
{
    public class AdminUserController : Controller
    {
        //
        // GET: /AdminUser/

        public ActionResult Index()
        {
            return View();
        }

        //
        // GET: /AdminUser/Details/huanhv
        [Authorize]
        public ActionResult Details(string username)
        {
            return View(new UserFormViewModel(
                Roles.GetAllRoles(),
                Roles.GetRolesForUser(username),
                Membership.GetUser(username),
                ViewMode.Details));
        }

        [Authorize]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Details(string userName, FormCollection formCollection)
        {
            var is_Deleted = formCollection["Delete"];

            if (!String.IsNullOrEmpty(is_Deleted) && String.Compare(is_Deleted, userName, true) == 0)
            {
                Membership.DeleteUser(userName, true);
                return RedirectToAction("List");
            }
            else
            {
                // If the user is deleted, then we don't have to execute this code...

                // Resetting the password
                ResetPassword(userName, formCollection);

                // Resetting the roles...
                // To do: Is there a better way to do this?
                var userRoles = String.IsNullOrEmpty(formCollection["UserRoles"]) ? new string[] { } : formCollection["UserRoles"].Split(',');
                ResetRserRoles(userName, userRoles);

                // Unlocking the user
                var unlock = String.IsNullOrEmpty(formCollection["IsLockedOut"]) ? String.Empty : formCollection["IsLockedOut"];
                if (!String.IsNullOrEmpty(unlock))
                {
                    MembershipUser user = Membership.GetUser(userName);
                    user.UnlockUser();
                }
            }

            return View(new UserFormViewModel(Roles.GetAllRoles(), Roles.GetRolesForUser(userName), Membership.GetUser(userName), ViewMode.Details));
        }

        private void ResetRserRoles(string userName, string[] newUserRoles)
        {
            // Need to clear all the existing roles
            var existingUserRoles = Roles.GetRolesForUser(userName);
            foreach (var role in existingUserRoles)
            {
                Roles.RemoveUserFromRole(userName, role);
            }

            // Set the new roles
            foreach (var role in newUserRoles)
            {
                Roles.AddUserToRole(userName, role);
            }
        }

        private void ResetPassword(string userName, FormCollection formCollection)
        {
            var old_password = formCollection["OldPassword"];
            var new_password = formCollection["NewPassword"];
            var confirm_password = formCollection["ConfirmPassword"];

            if (Extensions.StringHasValue(old_password) && Extensions.StringHasValue(new_password) && Extensions.StringHasValue(confirm_password))
            {
                if (String.Compare(new_password, confirm_password, false) == 0)
                {
                    var user = Membership.GetUser(userName);
                    if (user != null)
                    {
                        if (!user.ChangePassword(old_password, new_password))
                        {
                            ModelState.AddModelError("_FORM", "The password was not changed");
                        }
                    }
                }
                else
                {
                    ModelState.AddModelError("NewPassword", "The new password & confirm password don't match");
                }
            }
        }

        //
        // GET: /AdminUser/Create

        public ActionResult Create()
        {
            return View(new UserFormViewModel(
                    Roles.GetAllRoles(), null, null,
                    ViewMode.Create
                ));
        }

        //
        // POST: /AdminUser/Create

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(FormCollection collection)
        {
            try
            {
                // TODO: Add insert logic here
                string username = collection["UserName"];
                string password = collection["NewPassword"];
                string email = collection["Email"];

                MembershipCreateStatus status;
                Membership.CreateUser(username, password, email, null, null, true, out status);

                if (status == MembershipCreateStatus.Success)
                {
                }
                return RedirectToAction("List");
            }
            catch
            {
                return View();
            }
        }

        //
        // GET: /AdminUser/Edit/huanhv

        public ActionResult Edit(string username)
        {
            return View(new UserFormViewModel(
                    Roles.GetAllRoles(),
                    Roles.GetRolesForUser(username),
                    Membership.GetUser(username),
                    ViewMode.Edit
                ));
        }

        //
        // POST: /AdminUser/Edit/huanhv

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(string username, FormCollection collection)
        {
            try
            {
                MembershipUser currentUser = Membership.GetUser(username);

                // TODO: Add update logic here
                string newEmail = collection["Email"];
                string newRoleAsString = collection["UserRoles"];

                if (!currentUser.Email.Equals(newEmail))
                {
                    currentUser.Email = newEmail;
                    Membership.UpdateUser(currentUser);
                }

                string[] currentRoles = Roles.GetRolesForUser(username);
                string[] newRoles = newRoleAsString.Split(',');
                List<string> removedRoles = new List<string>();
                List<string> addedRoles = new List<string>();

                foreach (string role in newRoles)
                {
                    if (!currentRoles.Contains(role))
                    {
                        addedRoles.Add(role);
                    }
                }
                foreach (string role in currentRoles)
                {
                    if (!newRoleAsString.Contains(role))
                    {
                        removedRoles.Add(role);
                    }
                }
                if (removedRoles.Count > 0)
                {
                    Roles.RemoveUserFromRoles(username, removedRoles.ToArray());
                }
                if (addedRoles.Count > 0)
                {
                    Roles.AddUserToRoles(username, addedRoles.ToArray());
                }

                return RedirectToAction("List");
            }
            catch
            {
                return View();
            }
        }

        public ActionResult List(int? page)
        {
            var pagedUsers = new PaginatedList<MembershipUser>(Membership.GetAllUsers().Cast<MembershipUser>().AsQueryable<MembershipUser>(), page.HasValue ? page.Value : 0, 10);
            return View(pagedUsers);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult List(int? pageIndex, FormCollection formCollection)
        {
            var deletedUsers = (!Extensions.StringHasValue(formCollection["Delete"])) ? (new string[] { }) : (formCollection["Delete"].Split(','));
            var lockedUsers = (!Extensions.StringHasValue(formCollection["IsLockedOut"])) ? (new string[] { }) : (formCollection["IsLockedOut"].Split(','));

            // Check if users need to be deleted
            if (deletedUsers.Count() > 0)
            {
                foreach (var username in deletedUsers)
                {
                    Membership.DeleteUser(username, true);
                }
            }

            // Unlocking the users
            if (lockedUsers.Count() > 0)
            {
                foreach (string username in lockedUsers)
                {
                    // Check if the user has been marked for delete...
                    if (!deletedUsers.Contains(username))
                    {
                        Membership.GetUser(username).UnlockUser();
                    }
                }
            }

            // More options... I really hate this multi-looping code
            // Need to look for a better way of doing this...

            return RedirectToAction("List", new { pageIndex = pageIndex });
        }
    }
}
